
use std::io::{Write, BufReader, BufRead};
use std::fs::{File, OpenOptions};

use cross_rs::IResult;

use super::path_io;




pub fn read_bytes(file: &str) -> IResult<Vec<u8>> {
    match std::fs::read(file) {
        Ok(v) => Ok(v),
        Err(e) => {
            return cross_rs::errors::get_error(&format!("file_io::read_bytes: read file {file} error: {:?}", e));
        },
    }
}

pub fn write_bytes(bts: &Vec<u8>, file: &str) -> IResult {
    let mut file_hndl = match std::fs::File::create(&file) {
        Ok(v) => v,
        Err(e) => return Err(format!("file_io::write_bytes, create {file} error: {:?}", e).as_str())?,
    };

    match file_hndl.write_all(&bts) {
        Ok(_) => (),
        Err(e) => return Err(format!("file_io::read_bytes, write {file} error: {:?}", e).as_str())?,
    }
    Ok(())
}



pub fn read_utf8_lines(file_text: &str) -> IResult<Vec<String>> {
    let fs = match File::open(file_text) {
        Ok(v) => v,
        Err(e) => {
            return cross_rs::errors::get_error(&format!("file_io::read_utf8_lines: read file {file_text} error: {:?}", e));
        }
    };

    let mut lines: Vec<String> = vec![];
    let reader = BufReader::new(fs);
    for line_result in reader.lines() {
        match line_result {
            Err(_e) => {
              //  println!("{:?}", e);
            },
            Ok(line) => {
                lines.push(line);
            }
        }
    }

    return Ok(lines);
}

pub fn read_utf8(file_text: &str) -> IResult<String> {
    match std::fs::read_to_string(file_text) {
        Ok(v) => Ok(v),
        Err(e) => {
            return cross_rs::errors::get_error(&format!("file_io::read_utf8: read file {file_text} error: {:?}", e));
        },
    }
}

pub fn write_utf8(file_text: &str, buf: &String) -> IResult {
    let mut f = match File::create(file_text) {
        Ok(v) => v,
        Err(e) => {
            return cross_rs::errors::get_error(&format!("file_io::write_utf8: open file {file_text} error: {:?}", e));
        },
    };
    if let Err(e) = f.write_all(buf.as_bytes()) {
        return cross_rs::errors::get_error(&format!("file_io::write_utf8: write file {file_text} error: {:?}", e));
    }
    
    Ok(())
}

pub fn write_many_bytes(file_bin: &str, blobs: Vec<Vec<u8>>) -> IResult {
    let mut file_hndl = File::create(file_bin)?;
    for blob in blobs {
        file_hndl.write_all(&blob)?;
    }
    Ok(())
}
pub fn append_many_bytes(file_bin: &str, blobs: Vec<Vec<u8>>) -> IResult {
    let mut file_hndl = if path_io::is_file(file_bin) {
        OpenOptions::new().append(true).open(file_bin)?
    } else {
        File::create(file_bin)?
    };
    for blob in blobs {
        file_hndl.write_all(&blob)?;
    }
    Ok(())
}

const KB_F64: f64 = 1024_f64;

pub fn size2string(size: i64) -> String {
    if size <= 0 {
        return "0".to_string();
    }
    if size < 1_0000 {
        return format!("{size} b");
    }
    let kb = size as f64 / KB_F64;
    if kb < 1100.0 {
        return format!("{kb:.1} Kb");
    }
    let mb = kb / KB_F64;
    if mb < 1100.0 {
        return format!("{mb:.1} Mb");
    }
    let gb = mb / KB_F64;
    if gb < 1100.0 {
        return format!("{gb:.1} Gb");
    }
    let tb = gb / KB_F64;
    format!("{tb:.1} Tb")

}